//! 标量（scalar）类型表示单个值。
//! Rust 有 4 个基本的标量类型：整型、浮点型、布尔型和字符。

/// 整数类型演示
///
/// 整数类型可以分为有符号和无符号两种：
/// - 有符号整型以 `i` 开头，可以表示正数、零和负数
/// - 无符号整型以 `u` 开头，只能表示正数和零
///
/// 常见的整数类型：
///
/// | 长度   | 有符号类型 | 无符号类型 |
/// |--------|------------|------------|
/// | 8 位   | i8         | u8         |
/// | 16 位  | i16        | u16        |
/// | 32 位  | i32        | u32        |
/// | 64 位  | i64        | u64        |
/// | 128 位 | i128       | u128       |
/// | arch   | isize      | usize      |
///
/// 每个有符号类型规定的数字范围是 -(2^n - 1) ~ 2^(n - 1) - 1，其中 n 是该定义形式的位长度。
/// 所以 `i8` 可存储数字范围是 -(2^7) ~ 2^7 - 1，即 -128 ~ 127。
/// 无符号类型可以存储的数字范围是 0 ~ 2^n - 1，所以 `u8` 能够存储的数字为 0 ~ 2^8 - 1，即 0 ~ 255。
/// 此外，`isize` 和 `usize` 类型取决于程序运行的计算机体系结构，在表中表示为"arch"：
/// 若使用 64 位架构系统则为 64 位，若使用 32 位架构系统则为 32 位。
/// 你可以按照上述表格所示的任意形式来编写整型的字面量。
/// 注意，可能属于多种数字类型的数字字面量允许使用类型后缀来指定类型，例如 `57u8`。
/// 数字字面量还可以使用 `_` 作为可视分隔符以方便读数，如 `1_000`，此值和 `1000` 相同。
#[allow(unused_variables)]
pub fn integer_types() {
    // 声明不同类型的整数
    let a: i32 = 42; // 32位有符号整数
    let b: u64 = 100; // 64位无符号整数
    let c = 255u8; // 使用后缀指定类型
    let d = 1_000_000i64; // 使用下划线提高可读性

    println!("整数类型示例:");
    println!("i32: {}", a);
    println!("u64: {}", b);
    println!("u8: {}", c);
    println!("i64: {}", d);
}

/// 浮点类型演示
///
/// Rust 有两种基本的浮点类型：
/// - f32: 32位浮点数（单精度）
/// - f64: 64位浮点数（双精度，默认类型）
pub fn float_types() {
    let x: f64 = 2.0; // f64（默认）
    let y: f32 = 4.25; // f32

    println!("浮点类型示例:");
    println!("f64: {x}");
    println!("f32: {y}");
}

/// 数值运算演示
pub fn numeric_operations() {
    // 基本运算
    let sum = 5 + 10; // 加法
    let difference = 95.5 - 4.3; // 减法
    let product = 4 * 30; // 乘法
    let quotient = 56.7 / 32.2; // 除法
    let remainder = 43 % 5; // 取余

    println!("数值运算示例:");
    println!("5 + 10 = {sum}");
    println!("95.5 - 4.3 = {difference}");
    println!("4 * 30 = {product}");
    println!("56.7 / 32.2 = {quotient}");
    println!("43 % 5 = {remainder}");
}

/// 布尔类型演示
///
/// 布尔类型有两个可能的值：true 和 false
pub fn boolean_type() {
    let t = true;
    let f: bool = false; // 显式指定类型

    println!("布尔类型示例:");
    println!("true: {t}");
    println!("false: {f}");
}

/// 字符类型演示
///
/// Rust 的 char 类型是 Unicode 标量值，可以表示比 ASCII 多得多的内容
pub fn char_type() {
    let c = 'z';
    let z = 'ℤ';
    let heart_eyed_cat = '😻';

    println!("字符类型示例:");
    println!("英文字母: {c}");
    println!("数学符号: {z}");
    println!("emoji: {heart_eyed_cat}");
}

/// 类型转换演示
///
/// 在 Rust 中，必须显式地进行类型转换
pub fn type_conversion() {
    let decimal = 65.4321_f32;

    // 使用 as 关键字进行类型转换
    let integer = decimal as u8;
    let character = integer as char;

    println!("类型转换示例:");
    println!("Casting: {decimal} -> {integer} -> {character}");
}

/// 整型溢出处理演示
///
/// Rust 提供了多种处理整型溢出的方法：
///
/// | 方法            | 溢出行为                       | 返回值        | 适用场景                     |
/// |----------------|--------------------------------|---------------|------------------------------|
/// | `wrapping_*`   | 二进制补码包裹（循环回绕）      | 直接返回结果值 | 密码学、循环缓冲区、哈希算法   |
/// | `checked_*`    | 返回`None`                     | `Option<T>`   | 需要明确处理错误的场景         |
/// | `overflowing_*`| 返回结果和溢出标志              | `(T, bool)`   | 需要知道是否溢出的场景         |
/// | `saturating_*` | 饱和到类型的最大或最小值        | 直接返回结果值 | 图形处理、信号处理             |
pub fn integer_overflow() {
    let mut value: u8 = 255;

    // 调试模式：panic
    // value += 1; // 取消注释在调试模式会 panic!

    // 发布模式：二进制补码包裹
    value = value.wrapping_add(1); // 0
    println!("包裹后的值: {value}"); // 输出 0

    // wrapping_* - 包裹操作
    let a: u8 = 255;
    let b: u8 = 10;

    // 加法
    let wrap_add = a.wrapping_add(b); // 255 + 10 = 265 => 包裹为 9 (265 - 256 = 9)

    // 减法
    let wrap_sub_overflow = 0u8.wrapping_sub(1); // 0 - 1 = 255

    // 乘法
    let wrap_mul = a.wrapping_mul(2); // 255 * 2 = 510 => 254 (510 - 256 = 254)

    println!("包裹操作:");
    println!("加法: 255 + 10 = {wrap_add}"); // 9
    println!("减法: 0 - 1 = {wrap_sub_overflow}"); // 255
    println!("乘法: 255 * 2 = {wrap_mul}"); // 254

    // checked_* - 安全检查
    // 加法
    let checked_add = a.checked_add(b); // Some(265) -> None

    // 减法
    let checked_sub_overflow = 0u8.checked_sub(1); // None

    // 乘法
    let checked_mul = a.checked_mul(2); // None

    println!("\n安全检查:");
    println!("加法: 255 + 10 = {checked_add:?}"); // None
    println!("减法: 0 - 1 = {checked_sub_overflow:?}"); // None
    println!("乘法: 255 * 2 = {checked_mul:?}"); // None

    // overflowing_* - 溢出检测
    // 加法
    let (add_result, add_overflow) = a.overflowing_add(b); // (9, true)

    // 减法
    let (sub_overflow_result, sub_overflow_flag) = 0u8.overflowing_sub(1); // (255, true)

    // 乘法
    let (mul_result, mul_overflow) = a.overflowing_mul(2); // (254, true)

    println!("\n溢出检测:");
    println!("加法: 255 + 10 = {add_result} (溢出: {add_overflow})"); // 9, true
    println!("减法: 0 - 1 = {sub_overflow_result} (溢出: {sub_overflow_flag})"); // 255, true
    println!("乘法: 255 * 2 = {mul_result} (溢出: {mul_overflow})"); // 254, true

    // saturating_* - 饱和运算
    // 加法
    let saturating_add = a.saturating_add(b); // 255 (达到最大值)

    // 减法
    let saturating_sub_overflow = 0u8.saturating_sub(1); // 0 (达到最小值)

    // 乘法
    let saturating_mul = a.saturating_mul(2); // 255 (达到最大值)

    println!("\n饱和运算:");
    println!("加法: 255 + 10 = {saturating_add}"); // 255
    println!("减法: 0 - 1 = {saturating_sub_overflow}"); // 0
    println!("乘法: 255 * 2 = {saturating_mul}"); // 255
}

/// 位运算演示
pub fn bitwise_operations() {
    // 短路求值的布尔逻辑
    let (x, y) = (true, false);

    // 使用变量替代字面量，避免 Clippy 警告
    println!("x AND y is {} (x={}, y={})", x && y, x, y); // 实际计算 y
    println!("x OR y is {} (x={}, y={})", x || y, x, y); // 跳过计算 y
    println!("NOT x is {} (x={})", !x, x);
    // 位运算
    println!("\n位运算:");
    println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101);
    println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101);
    println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101);
    println!("1 << 5 is {}", 1u32 << 5);
    println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2);

    // 使用下划线改善数字的可读性！
    println!("\n数字可读性:");
    println!("One million is written as {}", 1_000_000u32);
}

/// 幂运算演示
pub fn power_operations() {
    let base = 2u32;
    let exponent = 8;
    let result = base.pow(exponent);
    println!("幂运算:");
    println!("{}^{} = {}", base, exponent, result);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_integer_types() {
        integer_types(); // 确保函数可以正常运行
    }

    #[test]
    fn test_float_types() {
        float_types(); // 确保函数可以正常运行
    }

    #[test]
    fn test_numeric_operations() {
        numeric_operations(); // 确保函数可以正常运行
    }

    #[test]
    fn test_boolean_type() {
        boolean_type(); // 确保函数可以正常运行
    }

    #[test]
    fn test_char_type() {
        char_type(); // 确保函数可以正常运行
    }

    #[test]
    fn test_type_conversion() {
        type_conversion(); // 确保函数可以正常运行
    }

    #[test]
    fn test_integer_overflow() {
        integer_overflow(); // 确保函数可以正常运行
    }

    #[test]
    fn test_bitwise_operations() {
        bitwise_operations(); // 确保函数可以正常运行
    }

    #[test]
    fn test_power_operations() {
        power_operations(); // 确保函数可以正常运行
    }
}
